﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms.Design;
using System.Windows.Forms.Integration;
using System.Threading;

namespace comm.editor
{
    public class ComputingExprDicEditor : UITypeEditor
    {
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.DropDown;
        }
        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            var edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            if (edSvc != null)
            {
                var elHost = new ElementHost
                {
                    Width = 800,
                    Height = 360,
                    Child = new UCComputingExprDic((Dictionary<string, string>)value)
                };
                edSvc.DropDownControl(elHost);
                return value;
            }
            return value;
        }
    }

    /// <summary>
    /// UCComputingExprDic.xaml 的交互逻辑
    /// </summary>
    public partial class UCComputingExprDic : UserControl
    {
        Dictionary<string, string> _exprDic = null;
        string _lastThId = "";

        public UCComputingExprDic(Dictionary<string, string> exprDic)
        {
            InitializeComponent();

            _exprDic = exprDic;

            cbSave.Items.Add("null");
            cbSave.Items.Add("NeedSave");
            cbSave.Items.Add("NoSave");
            cbSave.SelectionChanged += new SelectionChangedEventHandler(cbSave_SelectionChanged);

            var groups = EnumHelper.GetNames(typeof(objst.NValueGroup));
            cbNValueGroup.Items.Add("null");
            foreach (var group in groups)
            {
                cbNValueGroup.Items.Add(group);
            }
            cbNValueGroup.SelectionChanged += new SelectionChangedEventHandler(cbNValueGroup_SelectionChanged);
            cbNValueGroup.SelectedIndex = 0;
            cbSave.SelectedIndex = 1;

            btnAdd.Click += new RoutedEventHandler(btnAdd_Click);
            btnAddAll.Click += new RoutedEventHandler(btnAddAll_Click);
            btnClear.Click += new RoutedEventHandler(btnClear_Click);
            tbSearch.TextChanged += new TextChangedEventHandler(tbSearch_TextChanged);

            Fill();
        }

        void tbSearch_TextChanged(object sender, TextChangedEventArgs e)
        {
            comm.ThreadHelper.Stop(_lastThId);
            _lastThId = comm.ThreadHelper.Run(() =>
            {
                Thread.Sleep(200);
                Dispatcher.BeginInvoke(new Action(() =>
                {
                    Fill();
                }));
            });
        }
        void btnClear_Click(object sender, RoutedEventArgs e)
        {
            _exprDic.Clear();
            Fill();
        }
        void btnAddAll_Click(object sender, RoutedEventArgs e)
        {
            if (cbNValue.Items.Count > 0)
            {
                foreach (var item in cbNValue.Items)
                {
                    var tb = (TextBlock)item;
                    var key = tb.Tag.ToString();
                    if (!_exprDic.ContainsKey(key))
                    {
                        var nvalue = DefineFile.LastInstance.GetNValue(key);
                        _exprDic.Add(key, "");
                    }
                }
                Fill();
            }
        }
        void btnAdd_Click(object sender, RoutedEventArgs e)
        {
            if (cbNValue.SelectedIndex != -1)
            {
                var tb = (TextBlock)cbNValue.SelectedItem;
                var key = tb.Tag.ToString();
                if (!_exprDic.ContainsKey(key))
                {
                    var nvalue = DefineFile.LastInstance.GetNValue(key);
                    _exprDic.Add(key, "");
                    Fill();
                }
            }
        }
        void cbSave_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            cbNValueGroup_SelectionChanged(cbNValueGroup, null);
        }
        void cbNValueGroup_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (cbNValueGroup.SelectedIndex != -1)
            {
                comm.objst.NValueGroup? group = null;
                bool? save = null;
                if (cbSave.SelectedIndex == 1)
                {
                    save = true;
                }
                else if (cbSave.SelectedIndex == 2)
                {
                    save = false;
                }
                if (cbNValueGroup.SelectedItem.ToString() != "null")
                {
                    group = comm.EnumHelper.Parse<comm.objst.NValueGroup>(cbNValueGroup.SelectedItem.ToString());
                }
                var nvalueDic = DefineFile.LastInstance.GetAllNValue(group, save);
                cbNValue.Items.Clear();
                foreach (var key in nvalueDic.Keys)
                {
                    var item = nvalueDic[key];
                    var tb = new TextBlock
                    {
                        Tag = key,
                        Text = key + (item.Save ? "(save)" : ""),
                        Opacity = item.Save ? 1 : .7
                    };
                    if (_exprDic.ContainsKey(key))
                    {
                        tb.FontWeight = FontWeights.Bold;
                    }
                    cbNValue.Items.Add(tb);
                }
                if (cbNValue.Items.Count > 0)
                {
                    cbNValue.SelectedIndex = 0;
                }
            }
        }

        void Fill()
        {
            cbNValueGroup_SelectionChanged(cbNValueGroup, null);

            var nvalueDic = DefineFile.LastInstance.GetAllNValue();
            var dic = new Dictionary<string, string>();
            foreach (var key in nvalueDic.Keys)
            {
                if (_exprDic.ContainsKey(key))
                {
                    var nvalue = nvalueDic[key];
                    dic.Add(key, _exprDic[key]);
                }
            }
            _exprDic.Clear();
            foreach (var key in dic.Keys)
            {
                _exprDic.Add(key, dic[key]);
            }

            spList.Children.Clear();
            var stxt = tbSearch.Text.Trim().ToLower();
            foreach (var key in _exprDic.Keys)
            {
                var nvalue = DefineFile.LastInstance.GetNValue(key);
                var key2 = key;
                if (key.ToString().ToLower().IndexOf(stxt) == -1)
                {
                    continue;
                }
                var sp = new StackPanel
                {
                    Orientation = Orientation.Horizontal,
                    Margin = new Thickness(0, 0, 4, 4)
                };

                #region tbKey
                var tbKey = new TextBlock
                {
                    Text = key,
                    Width = 160,
                    TextAlignment = TextAlignment.Right,
                    Margin = new Thickness(0, 0, 4, 0),
                    VerticalAlignment = VerticalAlignment.Center,
                    Opacity = nvalue.Save ? 1 : .6
                };
                sp.Children.Add(tbKey);
                #endregion

                #region tbKey2
                var tbKey2 = new TextBox
                {
                    Text = _exprDic[key].ToString(),
                    Width = 60,
                    Margin = new Thickness(0, 0, 4, 0),
                    VerticalAlignment = VerticalAlignment.Center,
                    BorderBrush = new SolidColorBrush(Colors.Gray)
                };
                tbKey2.GotFocus += new RoutedEventHandler((o, e) =>
                {
                    tbKey.Background = new SolidColorBrush(Colors.Gray);
                    tbKey2.BorderBrush = new SolidColorBrush(Colors.Black);
                });
                tbKey2.LostFocus += new RoutedEventHandler((o, e) =>
                {
                    tbKey.Background = null;
                    tbKey2.BorderBrush = new SolidColorBrush(Colors.Gray);
                });
                tbKey2.TextChanged += new TextChangedEventHandler((o, e) =>
                {
                    var com = comm.objst.NValueComputing.Parse(tbKey2.Text);
                    if (com != null)
                    {
                        _exprDic[key2] = tbKey2.Text;
                        tbKey2.Text = _exprDic[key2].ToString();
                        tbKey2.Opacity = 1;
                    }
                    else
                    {
                        tbKey2.Opacity = .5;
                    }
                });
                sp.Children.Add(tbKey2);
                #endregion

                #region btnDel
                var btnDel = new Button
                {
                    Focusable = false,
                    Content = "X",
                    Width = 22,
                    Height = 22,
                    VerticalAlignment = VerticalAlignment.Center
                };
                btnDel.Click += new RoutedEventHandler((o, e) =>
                {
                    _exprDic.Remove(key2);
                    cbNValueGroup_SelectionChanged(cbNValueGroup, null);
                    Fill();
                });
                sp.Children.Add(btnDel);
                #endregion

                if (stxt != "")
                {
                    #region hightlight
                    var ss = comm.StringHelper.SplitText(tbKey.Text, stxt);
                    var txt = tbKey.Text;
                    tbKey.Text = "";
                    if (ss[0] != null)
                    {
                        tbKey.Inlines.Add(new TextBlock { Text = ss[0] });
                    }
                    if (ss[1] != null)
                    {
                        tbKey.Inlines.Add(new TextBlock
                        {
                            FontWeight = FontWeights.Bold,
                            Foreground = new SolidColorBrush(Colors.Red),
                            Text = ss[1]
                        });
                    }
                    if (ss[2] != null)
                    {
                        tbKey.Inlines.Add(new TextBlock { Text = ss[2] });
                    }
                    #endregion
                }

                spList.Children.Add(sp);
            }
        }
    }
}
